package com.fjwt.gz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjwt.gz.components.oss.model.MockMultipartFile;
import com.fjwt.gz.components.oss.model.OssFileConfig;
import com.fjwt.gz.components.oss.service.OssFileService;
import com.fjwt.gz.core.cache.ITokenService;
import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.core.constants.ApiCodeEnum;
import com.fjwt.gz.core.constants.CS;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.jwt.JWTPayload;
import com.fjwt.gz.core.jwt.JWTUtils;
import com.fjwt.gz.core.model.ApiRes;
import com.fjwt.gz.core.model.security.GzUserDetails;
import com.fjwt.gz.core.utils.WxUtil;
import com.fjwt.gz.db.base.BaseAgentApp;
import com.fjwt.gz.db.dto.*;
import com.fjwt.gz.db.entity.*;
import com.fjwt.gz.db.vo.*;
import com.fjwt.gz.service.mapper.*;
import com.fjwt.gz.zhyx.sms.SmsUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.fjwt.gz.core.constants.CS.getVersionKeyToken;


/**
 * <p>
 * 会员信息基础表（18个地市进行关联） 服务实现类
 * </p>
 *
 * @author shiyonghao
 * @since 2025-04-09
 */
@Slf4j
@Service
public class FansService extends ServiceImpl<FansMapper, FansEntity> {

    @Autowired
    private FansMapper fansMapper;
    @Autowired
    private FansMchMapper fansMchMapper;
    @Autowired
    private FansUserService fansUserService;
    @Autowired
    private MchInfoService mchInfoService;
    @Autowired
    private FansAgentService fansAgentService;
    @Autowired
    private FansSourceService fansSourceService;
    @Autowired
    private AgentEmployeeService agentEmployeeService;
    @Autowired
    private AgentAppService agentAppService;
    @Autowired
    private AgentInfoService agentInfoService;
    @Autowired
    private AwardCouponService awardCouponService;
    @Autowired
    private AwardGoodsService awardGoodsService;
    @Autowired
    private AwardVirtualService awardVirtualService;
    @Autowired
    private ScoreTotalService scoreTotalService;
    @Autowired
    private FansAwardService fansAwardService;
    @Autowired
    private AwardVirtualInsideService virtualGoodsInsideService;
    @Autowired
    private AwardVirtualService virtualAwardService;
    @Autowired
    private AssetMonthService assetMonthService;
    @Autowired
    private AgentEquityService agentEquityService;
    @Autowired
    private OssRecordService ossRecordService;
    @Autowired
    private ScoreRecordTotalMapper scoreRecordTotalMapper;
    @Autowired
    private OssFileService ossFileService;
    @Autowired
    private FansAuthService fansAuthService;
    @Autowired
    private AssetQuarterService assetQuarterService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private AgentAppMapper agentAppMapper;
    @Autowired
    private InviterRecordService inviterRecordService;
    @Autowired
    private AgentScoreRuleMapper agentScoreRuleMapper;
    @Autowired
    private OldFansInfoService oldFansInfoService;
    @Autowired
    private FansAuthMapper fansAuthMapper;
    @Autowired
    private FansUserMapper fansUserMapper;
    @Autowired
    private FansSourceMapper fansSourceMapper;
    @Autowired
    private OldFansInfoMapper oldFansInfoMapper;

    public Map<String, Object> selectById(Long fansId, String appid, String locationAgentNo) {
        Map<String, Object> map = fansMapper.selectByFansId(fansId, appid, locationAgentNo);
        Map<String, Object> copyOf = Map.copyOf(map);
        return copyOf;
    }

    public FansEntity selectFansByOpenId(String openid , String locationAgentNo) {
        FansEntity entity = fansMapper.selectFansByOpenId(openid, locationAgentNo);
        FansEntity result = new FansEntity();
        BeanUtils.copyProperties(entity, result);
        return result;
    }

    /**
     * 获取一鑫支付公众号openid
     *
     * @return
     */
    public FansEntity getWxchatPayOpenid(String appId, String secret, String code, boolean environment,String locationAgentNo) {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("appid", appId);
        paramMap.put("secret", secret);
        paramMap.put("code", code);
        paramMap.put("grant_type", "authorization_code");
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
        //可以单独传入http参数，这样参数会自动做URL编码，拼接在URL中
        String result3 = HttpUtil.get(url, paramMap);
        //先转成JSON对象
        JSONObject jsonObject = JSONObject.parseObject(result3);
        log.info("微信支付公众号中的openid：{}", jsonObject.getString("openid"));
        // 支付公众号的openid
        String openid = jsonObject.getString("openid");
        FansEntity fansEntity = this.selectFansByOpenId(openid,locationAgentNo);
        if (null != fansEntity) {
            return fansEntity;
        }
        // 查库
        FansEntity entity = this.insertFansEntity(openid,locationAgentNo);
        return entity;
    }

    /**
     * 登录小程序并获取地域小程序的openid
     */
    public JSONObject getPlaceWxchatOpenid(String payOpenid, String appId, String code, String inviterInfo, Integer inviterType, Long fansId, String jwtSecret, String locationAgentNo) {
        Long userId = 0L;
        Integer isLogin = 0;
        String placeOpenId = "";
        log.info("用户来源信息：{}，地域小程序appid：{},用户id：{},微信code：{},支付公众号openid：{}，fansId:{}", inviterInfo, appId, fansId, code, payOpenid, fansId);
        if (StringUtils.isEmpty(appId) || StringUtils.isEmpty(code) || StringUtils.isEmpty(payOpenid) || StringUtils.isEmpty(locationAgentNo)) {
            throw new BizException("网络故障，请稍后重试！");
        }
        JSONObject json = this.getPlaceWxchatOpenids(userId,isLogin,placeOpenId,payOpenid,code,appId,fansId,inviterInfo,inviterType,locationAgentNo);

        // 生成token
        String cacheKey = CS.getCacheKeyToken(CS.SYS_ROLE_TYPE.MCH, fansId, json.getString("userId"));
        com.fjwt.gz.db.entity.SysUser sysUser = new com.fjwt.gz.db.entity.SysUser();
        sysUser.setSysUserId(Long.valueOf(fansId));
        GzUserDetails gzUserDetails = new GzUserDetails();
        gzUserDetails.setSysUser(sysUser);
        gzUserDetails.setUserId(json.getLong("userId"));
        gzUserDetails.setFansId(fansId);
        gzUserDetails.setAppId(appId);
        gzUserDetails.setAgentNo(locationAgentNo);
//        gzUserDetails.setMchNo(json.getString("mchNo"));
        //生成iToken 并放置到缓存
        ITokenService.processTokenCache(CS.SYS_ROLE_TYPE.MCH, gzUserDetails, cacheKey); //处理token 缓存信息
        //将信息放置到Spring-security context中
        UsernamePasswordAuthenticationToken authenticationRest = new UsernamePasswordAuthenticationToken(gzUserDetails, null, gzUserDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationRest);
        //返回JWTToken
        JWTPayload jwtPayload = new JWTPayload(gzUserDetails);
        log.info("JWTToken:{}", jwtPayload.toMap());
        String token = JWTUtils.generateToken(jwtPayload, jwtSecret);

        String dataKey = UUID.randomUUID().toString().replace("-", "").substring(0, 16);

        int version = Integer.parseInt(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));

        RedisUtil.setString(getVersionKeyToken(CS.SYS_ROLE_TYPE.MCH, json.getLong("userId"), "dataKey"), dataKey, CS.TOKEN_TIME);
        RedisUtil.setString(getVersionKeyToken(CS.SYS_ROLE_TYPE.MCH, json.getLong("userId"), "version"), String.valueOf(version), CS.TOKEN_TIME);
        JSONObject dynamicKey = new JSONObject();
        dynamicKey.put("dataKey", dataKey);
        dynamicKey.put("version", version);
        // 用户绑定机构
        FansSourceEntity fansSourceEntity = fansSourceService.findFansSourceByFansId(fansId,appId);
        json.put("token", token);
        json.put("isBind", (ObjectUtils.isEmpty(fansSourceEntity) || StringUtils.isEmpty(fansSourceEntity.getAgentNo())) ? 0 : 1);
        json.put("dynamicKey", dynamicKey);
        log.info("获取地域小程序用户的openid，返回结果：{}", JSONUtil.toJsonStr(json));
        return json;
    }

    /**
     * 获取地域小程序的openid
     */
    public JSONObject getPlaceWxchatOpenids(Long userId, Integer isLogin,String placeOpenId, String payOpenid, String code, String appId, Long fansId, String inviterInfo, Integer inviterType, String locationAgentNo) {
        String keyRedis = "placeAPPID:";
        JSONObject json = new JSONObject();
        FansEntity fanDto = fansMapper.selectFansByOpenId(payOpenid,locationAgentNo);
        log.info("支付公众号openid：{}，用户支付公众号fans信息：{}", payOpenid, JSON.toJSONString(fanDto));
        if (Objects.isNull(fanDto)) {
            throw new BizException(ApiCodeEnum.LITE_USER_ERROR);
        }

        // 获取地域小程序缓存信息
        String placeAPPID = RedisUtil.getString(keyRedis + appId);
        AgentAppEntity liteEntity = null;

        if (StringUtils.isEmpty(placeAPPID)) {
            LambdaQueryWrapper<AgentAppEntity> query = new LambdaQueryWrapper<>();
            query.eq(AgentAppEntity::getAppId, appId);
            query.eq(AgentAppEntity::getType, 1);
            query.eq(AgentAppEntity::getIsDeleted, 0);
            query.eq(AgentAppEntity::getIsDefault, 1);
            liteEntity = agentAppService.getBaseMapper().selectOne(query);
            if (Objects.isNull(liteEntity)) {
                throw new BizException("小程序配置有误，请联系管理员！");
            } else {
                RedisUtil.set(keyRedis + appId, liteEntity, 24, TimeUnit.HOURS);
            }
        } else {
            liteEntity = JSON.parseObject(placeAPPID, AgentAppEntity.class);
        }
        AgentAppEntity liteEntitys = agentAppService.lambdaQuery().eq(AgentAppEntity::getAgentNo, liteEntity.getAgentNo()).eq(AgentAppEntity::getType, 0)
                .eq(AgentAppEntity::getIsDeleted, 0).eq(AgentAppEntity::getIsDefault, 1).one();

        log.info("地域小程序配置信息：appid：{}，参数信息：{}", appId, JSON.toJSONString(liteEntity));
        log.info("地域公众号配置信息：{}", JSON.toJSONString(liteEntitys));
        LambdaQueryWrapper<SysConfig> queryConfig = new LambdaQueryWrapper<>();
        queryConfig.eq(SysConfig::getConfigKey, appId);
        SysConfig sysConfig = sysConfigService.getOne(queryConfig);
        JSONObject entitys = JSONObject.parseObject(sysConfig.getConfigVal());
        // 新用户信息
        Map<String, Object> wxUserInfo = WxUtil.getWxPlaceOpenId(code, appId, entitys.getString("appSecret"));
        log.info("微信认证参数：{}", JSON.toJSONString(wxUserInfo));
        if (!wxUserInfo.containsKey("openid")) {
            throw new BizException("登录失败");
        }
        String openid = MapUtil.getStr(wxUserInfo, "openid");
        // 查库
        FansUserEntity msgEntity = fansUserService.selectFansByOpenIdAndAppid("1", openid, appId);
        log.info("用户登录地域小程序信息fans:{}", JSON.toJSONString(msgEntity));
        FansUserEntity placeEntity = fansUserService.selectFansByFansIdAndAppid("0", fanDto.getFansId(), liteEntitys.getAppId());
        log.info("用户地域公众号信息：：{}", JSON.toJSONString(placeEntity));
        if (Objects.nonNull(placeEntity)) {
            placeOpenId = placeEntity.getOpenId();
            log.info("用户登录地域小程序信息获取用户地域公众号openid:{}", JSON.toJSONString(placeEntity));
        } else {
            log.info("该用户未存在地域公众号openid：用户fansId：{}", fansId);
        }
        // 入库操作
        if (Objects.isNull(msgEntity)) {
            FansUserEntity entity = new FansUserEntity();
            entity.setFansId(fanDto.getFansId());
            entity.setAppId(appId);
            entity.setType(1);
            entity.setCreatedAt(new Date());
            entity.setOpenId(openid);
            int insert = fansUserService.getBaseMapper().insert(entity);
            if (insert > 0) {
                //下面方法传参的时候，最后一个参数是inviterId【邀请id（客户经理：sys_user_id、商户：mchNo,消费者：fans_id,公众号：公众号app_id ,广告：微信、抖音）】
                this.insertFansSource(inviterType, inviterInfo, fanDto.getFansId(), appId);
                log.info("用户登录地域小程序信息fans:{}", JSON.toJSONString(entity));
                userId = entity.getFansUserId();

                msgEntity = entity;
            }
        } else {
            userId = msgEntity.getFansUserId();
            isLogin = msgEntity.getIsLogin();
        }
        json.put("openId", openid);
        json.put("fansId", fanDto.getFansId());
        json.put("userId", userId);
        json.put("placeOpenId", placeOpenId);
        json.put("agentNo", liteEntity.getAgentNo());
        json.put("agentNo2", liteEntity.getAgentNo2());
        json.put("placeAppid", liteEntitys.getAppId());//地域公众号appid
        json.put("isLogin", isLogin);
        json.put("state", msgEntity.getState());
        json.put("logoutTime", msgEntity.getLogoutTime() == null ? null : DateUtil.format(DateUtils.addDays(msgEntity.getLogoutTime(), 30), "yyyy-MM-dd"));
        return json;
    }

    /**
     * 个人详情信息
     */
    public Map<String, Object> getFansDetail(Long fansId, Long userId, String appid, String locationAgentNo) {
        //        临时性校验代码
        if (StringUtils.isEmpty(locationAgentNo)) {
            throw new BizException("小程序已更新，请重新进入小程序！");
        }

        if (Objects.isNull(fansId) || StringUtils.isEmpty(appid) || StringUtils.isEmpty(locationAgentNo)) {
            throw new BizException("网络故障，请稍后重试！");
        }
        Map<String, Object> map = this.selectById(fansId, appid, locationAgentNo);
        FansAgentEntity fansAgentEntity = fansAgentService.lambdaQuery().eq(FansAgentEntity::getFansId, fansId).eq(FansAgentEntity::getAppId, appid).eq(FansAgentEntity::getIsDeleted, Constants.IS_DELETED.NO).one();
        if (fansAgentEntity != null && fansAgentEntity.getAgentEmployeeId() != null){
            AgentEmployeeEntity fansAgent = agentEmployeeService.getById(fansAgentEntity.getAgentEmployeeId());
            if (fansAgent != null && fansAgent.getEmployeeName() != null){
                map.put("khjlAgentNo", fansAgent.getAgentNo());
            }
        }
        if (map != null) {
            LambdaQueryWrapper<FansAuthEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(FansAuthEntity::getFansId, fansId);
            queryWrapper.eq(FansAuthEntity::getAgentNo, locationAgentNo);
            FansAuthEntity fansAuthEntity = fansAuthService.getOne(queryWrapper);
            if (fansAuthEntity != null) {
                map.put("isAuth", fansAuthEntity != null && ObjectUtils.isNotEmpty(fansAuthEntity.getCstmNo()) ? 0 : 1);
                map.put("cstmNo", fansAuthEntity.getCstmNo());
                map.put("cstmName", fansAuthEntity.getCstmName());
//          查询资产等级接口
                final Map<String, Integer> mapasset = assetMonthService.getUserAssetLevel(map.get("cstmNo").toString(), fansId, locationAgentNo);
                if (mapasset.get("userAssetLevel") != null) {
                    map.put("assetLevel", String.valueOf(mapasset.get("userAssetLevel")));

                    LocalDate firstDayOfLastMonth = LocalDate.of(mapasset.get("year"), mapasset.get("lastMonth"), 1);
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM");

                    map.put("assetLevelDate", firstDayOfLastMonth.format(formatter));
                    map.put("inSearch", mapasset.get("inSearch"));
//                    AssetLevelEquityVO assetLevelEquity = equityMultiplierService.getAssetLevelEquity(mapasset.get("userAssetLevel"), locationAgentNo);
//                    if (assetLevelEquity != null) {
//                        map.put("levelScore", String.valueOf(assetLevelEquity.getLevelScore()));
//                    }
                } else {
                    LocalDate firstDayOfLastMonth = LocalDate.of(mapasset.get("year"), mapasset.get("lastMonth"), 1);
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM");

                    map.put("assetLevelDate", firstDayOfLastMonth.format(formatter));
                    map.put("inSearch", mapasset.get("inSearch"));
                }

                final Map<String, Integer> maps = assetQuarterService.quarterAssetLevel(fansId, map.get("cstmNo").toString(), locationAgentNo);
                if (maps.get("userAssetLevel") != null) {
                    map.put("year", maps.get("year"));
                    map.put("quarter", maps.get("quarter"));
                    map.put("quarterAssetLevel", String.valueOf(maps.get("userAssetLevel")));
                    map.put("quarterInSearch", maps.get("inSearch"));
                } else {
                    map.put("year", maps.get("year"));
                    map.put("quarter", maps.get("quarter"));
                    map.put("quarterInSearch", maps.get("inSearch"));
                }
            }
        } else {
            throw new BizException("请先登录！");
        }
        log.info("C端用户个人详情接口调用：请求地址：/api/fans/detail，返回结果：{}", JSONUtil.toJsonStr(map));
        return map;
    }

    /**
     * 用户绑定机构网点
     */
    public JSONObject findFansBindAgent(String lng, String lat, Long fansId, String appId, String locationAgentNo) {
        if (StringUtils.isEmpty(lng) || StringUtils.isEmpty(lat)) {
            throw new BizException("网络故障，请稍后重试！");
        }
        log.info("C端用户绑定机构网点接口调用：请求地址：/api/fans/findFansBindAgent，请求参数：用户fansId:{}，locationAgentNo:{}，lng:{}，lat:{}", fansId, locationAgentNo, lng, lat);
        FansSourceEntity entity = fansSourceService.findFansSourceByFansId(fansId,appId);
        FansSourceAgentVO agentVO = fansSourceService.findFansBindAgent(locationAgentNo, lng, lat);
        JSONObject json = new JSONObject();
        json.put("source", null == entity ? "" : entity);
        json.put("agent", agentVO);
        log.info("C端用户绑定机构网点接口调用：请求地址：/api/fans/findFansBindAgent，返回结果：{}", JSONUtil.toJsonStr(json));
        return json;
    }

    public ApiRes insertFansEntity(Long fansId, String agentNo, String appId) {
        if (null == fansId || StringUtils.isEmpty(agentNo)) {
            return ApiRes.customFail("网络故障，请稍后重试！");
        }
        LambdaQueryWrapper<FansSourceEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FansSourceEntity::getFansId, fansId);
        queryWrapper.eq(FansSourceEntity::getAppId, appId);
        FansSourceEntity entity = fansSourceService.getBaseMapper().selectOne(queryWrapper);
        if (null != entity) {
            if (StringUtils.isEmpty(entity.getAgentNo())) {
                FansSourceEntity dto = new FansSourceEntity();
                dto.setFansSourceId(entity.getFansSourceId());
                dto.setAgentNo(agentNo);
                boolean flag = fansSourceService.updateById(dto);
                return flag ? ApiRes.ok() : ApiRes.customFail("绑定机构网点失败！");
            }
            return ApiRes.customFail("已绑定该机构网点，请勿重复绑定！");
        } else {
            FansSourceEntity dto = new FansSourceEntity();
            dto.setAgentNo(agentNo);
            dto.setFansId(fansId);
            dto.setInviterType(0);
            dto.setCreatedAt(new Date());
            dto.setAppId(appId);
            AgentLevelDTO agentLevelDTO = agentInfoService.selectAgentLevel(agentNo);
            dto.setAgentNo1(agentLevelDTO.getAgentNo1());
            dto.setAgentNo2(agentLevelDTO.getAgentNo2());
            dto.setAgentNo3(agentLevelDTO.getAgentNo3());
            dto.setAgentNo4(agentLevelDTO.getAgentNo4());
            int i = fansSourceService.getBaseMapper().insert(dto);
            // 郑州同步存量用户归属信息
            if(i > 0 && "wx554f86dfa21d0373".equals(appId)){
                syncFansInfoAgentNo(fansId,appId,agentNo,dto.getFansSourceId());
            }
            return i > 0 ? ApiRes.ok() : ApiRes.customFail("绑定机构网点失败！");
        }
    }

    /**
     * 郑州存量用户同步归属信息
     *
     * @param fansId
     * @param appId
     */
    private void syncFansInfoAgentNo(Long fansId, String appId,String agentNo,Long fansSourceId){
        // 获取用户
        FansEntity fansEntity = fansMapper.selectById(fansId);
        // 公众号openId是否匹配
        FansUserEntity msgEntity = fansUserMapper.selectFansByFansIdAndAppid("0", fansId, "wx2a7a68d3bcb2ef2c");
        if(Objects.nonNull(msgEntity)){
            OldFansInfoEntity oldFansInfo = oldFansInfoService.selectOldFansInfoByOpenId(msgEntity.getOpenId());
            if(Objects.nonNull(oldFansInfo)){
                if(!"自然流量".equals(oldFansInfo.getAgentNo())){
                    // 更改fansSource的归属关系
                    fansSourceMapper.updateFansAgentNo(fansSourceId,oldFansInfo);
                }
                if("自然流量".equals(oldFansInfo.getAgentNo())){
                    // 变更oldFansInfo的归属关系
                    AgentLevelDTO dto = agentInfoService.selectAgentLevel(agentNo);
                    oldFansInfo.setNewAgentName1(dto.getAgentName1());
                    oldFansInfo.setNewAgentName2(dto.getAgentName2());
                    oldFansInfo.setNewAgentName3(dto.getAgentName3());
                    oldFansInfo.setNewAgentName4(dto.getAgentName4());
                    oldFansInfo.setNewAgentNo1(dto.getAgentNo1());
                    oldFansInfo.setNewAgentNo2(dto.getAgentNo2());
                    oldFansInfo.setNewAgentNo3(dto.getAgentNo3());
                    oldFansInfo.setNewAgentNo4(dto.getAgentNo4());
                    oldFansInfoService.updateById(oldFansInfo);
                }
            }
        }
        // 手机号是否匹配
        OldFansInfoEntity oldFansInfo = oldFansInfoMapper.selectOldScoreByPhone(fansEntity.getPhone());
        if(Objects.nonNull(oldFansInfo)){
            // 自然流量 需变更oldFansInfo的归属关系
            if("自然流量".equals(oldFansInfo.getAgentNo())){
                // 变更oldFansInfo的归属关系
                AgentLevelDTO dto = agentInfoService.selectAgentLevel(agentNo);
                oldFansInfo.setNewAgentName1(dto.getAgentName1());
                oldFansInfo.setNewAgentName2(dto.getAgentName2());
                oldFansInfo.setNewAgentName3(dto.getAgentName3());
                oldFansInfo.setNewAgentName4(dto.getAgentName4());
                oldFansInfo.setNewAgentNo1(dto.getAgentNo1());
                oldFansInfo.setNewAgentNo2(dto.getAgentNo2());
                oldFansInfo.setNewAgentNo3(dto.getAgentNo3());
                oldFansInfo.setNewAgentNo4(dto.getAgentNo4());
                oldFansInfoService.updateById(oldFansInfo);
            }
            // 需变更fansSource的归属关系
            if(!"自然流量".equals(oldFansInfo.getAgentNo())){
                // 更改fansSource的归属关系
                fansSourceMapper.updateFansAgentNo(fansSourceId,oldFansInfo);
            }
        }
    }

    public FansEntity getuserphonenumber(Long fansId, String code, String appId, Long userId, String locationAgentNo) {
        //        临时性校验代码
        if (StringUtils.isEmpty(locationAgentNo)) {
            throw new BizException("小程序已更新，请重新进入小程序！");
        }
        log.info("用户fansId：{}，客户id：{}，认证code：{}，小程序appid：{}，locationAgentNo:{}", fansId, userId, code, appId, locationAgentNo);
        if (null == fansId || StringUtils.isEmpty(code) || StringUtils.isEmpty(appId) || StringUtils.isEmpty(locationAgentNo)) {
            throw new BizException("网络故障，请稍后重试！");
        }
        BaseAgentApp agentApp = agentAppService.getAgentApp(appId);
        if (ObjectUtils.isEmpty(agentApp)) {
            throw new BizException("地域公众号信息不存在");
        }
        String phone = WxUtil.getPhoneNumber(code, appId, agentApp.getAppSecret());
        if (StringUtils.isEmpty(phone)) {
            throw new BizException("获取手机号失败");
        }
        //
        FansEntity fansEntity = new FansEntity();
        fansEntity.setFansId(fansId);
        JSONObject json = new JSONObject();
        json.put("phone", phone);
        fansEntity.setPhone(phone);
        try {
            this.updateById(fansEntity);
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                throw new BizException("手机号已被注册");
            }
            log.info("修改手机号异常：{}", e.getMessage());
            throw new BizException("网络波动，请重试");
        }
        //
        FansEntity entity = this.getById(fansId);
        FansEntity dto = new FansEntity();
        BeanUtils.copyProperties(entity, dto);
        FansSourceEntity fansSourceEntity = fansSourceService.findFansSourceByFansId(fansId,appId);
        if (null != fansSourceEntity) {
            dto.addExt("gswdAgentNo", fansSourceEntity.getAgentNo());
            AgentInfoEntity agentInfo = agentInfoService.getById(fansSourceEntity.getAgentNo());
            if (null == agentInfo) {
                dto.addExt("gswdPid", "");
            } else {
                dto.addExt("gswdPid", agentInfo.getPid());
                dto.addExt("gswdAgentName", agentInfo.getAgentName());
            }
        } else {
            dto.addExt("gswdPid", "");
            dto.addExt("gswdAgentNo", "");
        }
        FansUserEntity userEntity = fansUserService.getById(userId);
        dto.addExt("openId", userEntity.getOpenId());
        userEntity.setIsLogin(1);
        fansUserService.updateById(userEntity);
        FansAgentEntity fansAgentEntity = fansAgentService.lambdaQuery().eq(FansAgentEntity::getFansId, fansId).eq(FansAgentEntity::getAppId, appId).eq(FansAgentEntity::getIsDeleted, 0).one();
        if (null != fansAgentEntity){
            AgentEmployeeEntity agentEmployeeEntity = agentEmployeeService.lambdaQuery().eq(AgentEmployeeEntity::getAgentEmployeeId, fansAgentEntity.getAgentEmployeeId()).one();
            if (null != agentEmployeeEntity){
                dto.addExt("khjlAgentNo", null != agentEmployeeEntity && StringUtils.isNotEmpty(agentEmployeeEntity.getAgentNo()) ? agentEmployeeEntity.getAgentNo() : "");
            }
        }else {
            dto.addExt("khjlAgentNo", "");
        }
        FansUserEntity msgEntity = fansUserService.selectFansByFansIdAndAppid("0", fansEntity.getFansId(), appId);
        if (null == msgEntity) {
            dto.addExt("placeOpenId", "");
        } else {
            if (StringUtils.isEmpty(msgEntity.getOpenId())) {
                dto.addExt("placeOpenId", "");
            } else {
                dto.addExt("placeOpenId", msgEntity.getOpenId());
            }
        }
        LambdaQueryWrapper<FansAuthEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FansAuthEntity::getFansId, fansId);
        queryWrapper.eq(FansAuthEntity::getAgentNo, locationAgentNo);
        FansAuthEntity fansAuthEntity = fansAuthService.getOne(queryWrapper);
        dto.addExt("isAuth", fansAuthEntity != null && ObjectUtils.isNotEmpty(fansAuthEntity.getCstmNo()) ? 0 : 1);
        if (fansAuthEntity != null && ObjectUtils.isNotEmpty(fansAuthEntity.getCstmNo())) {
//          查询资产等级接口
            final Map<String, Integer> map = assetMonthService.getUserAssetLevel(fansAuthEntity.getCstmNo(), fansId, locationAgentNo);
            if (map.get("userAssetLevel") != null) {
                LocalDate firstDayOfLastMonth = LocalDate.of(map.get("year"), map.get("lastMonth"), 1);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM");

                dto.addExt("assetLevelDate", firstDayOfLastMonth.format(formatter));
                dto.addExt("assetLevel", String.valueOf(map.get("userAssetLevel")));
                dto.addExt("inSearch", map.get("inSearch"));
//                AssetLevelEquityVO assetLevelEquity = equityMultiplierService.getAssetLevelEquity(map.get("userAssetLevel"),agentNo);
//                if(assetLevelEquity!=null){
//                    dto.addExt("levelScore", String.valueOf(assetLevelEquity.getLevelScore()));
//                }
            } else {
                LocalDate firstDayOfLastMonth = LocalDate.of(map.get("year"), map.get("lastMonth"), 1);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM");
                dto.addExt("assetLevelDate", firstDayOfLastMonth.format(formatter));
                dto.addExt("inSearch", map.get("inSearch"));
            }
            final Map<String, Integer> maps = assetQuarterService.quarterAssetLevel(fansId, fansAuthEntity.getCstmNo(), locationAgentNo);
            if (maps.get("userAssetLevel") != null) {
                dto.addExt("year", maps.get("year"));
                dto.addExt("quarter", maps.get("quarter"));
                dto.addExt("quarterAssetLevel", String.valueOf(maps.get("userAssetLevel")));
                dto.addExt("quarterInSearch", maps.get("inSearch"));
            } else {
                dto.addExt("year", maps.get("year"));
                dto.addExt("quarter", maps.get("quarter"));
                dto.addExt("quarterInSearch", maps.get("inSearch"));
            }

        }
        dto.setPhone(phone);
        log.info("用户信息：{}", JSONObject.toJSONString(dto));
        return dto;
    }

    public FansUserEntity getChangChunPlaceOpenid(String code, String appid, Long fansId, SysConfig sysConfig,String locationAgentNo) {

        JSONObject entity = JSONObject.parseObject(sysConfig.getConfigVal());
        log.info("地域公众号信息：{}", JSONObject.toJSONString(entity));
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("appid", appid);
        paramMap.put("secret", entity.get("appSecret"));
        paramMap.put("code", code);
        paramMap.put("grant_type", "authorization_code");
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token";
        //可以单独传入http参数，这样参数会自动做URL编码，拼接在URL中
        String result3 = HttpUtil.get(url, paramMap);
        //先转成JSON对象
        JSONObject jsonObject = JSONObject.parseObject(result3);
        log.info("微信地域公众号中的openid：{}", jsonObject.getString("openid"));
        // 支付公众号的openid
        String openid = jsonObject.getString("openid");
        // 存量客户实名认证信息同步
        OldFansInfoEntity oldFansInfo = oldFansInfoService.selectOldFansInfoByOpenId(openid);
        log.info("存量客户信息：{}", JSONObject.toJSONString(oldFansInfo));
        if(ObjectUtils.isNotEmpty(oldFansInfo)){
            // 已实名
            if(0 == oldFansInfo.getIsAuth()){
                // 是否存在实名信息
                FansAuthEntity fansAuthEntity = fansAuthMapper.selectFansAuthByFansIdAndAgentNo(fansId, locationAgentNo);
                log.info("用户实名认证信息：{}",JSONObject.toJSONString(fansAuthEntity));
                // 不存在则新增
                if(null == fansAuthEntity){
                    FansAuthEntity result = new FansAuthEntity();
                    result.setFansId(fansId);
                    result.setAgentNo(locationAgentNo);
                    result.setCstmName(oldFansInfo.getRealName());
                    result.setAuthTime(oldFansInfo.getAuthTime());
                    result.setCstmNo(oldFansInfo.getCstmNo());
                    result.setAuthRepInfo(oldFansInfo.getCstmInfo());
                    result.setAuthPhone(oldFansInfo.getPhone());
                    fansAuthMapper.insert(result);
                }
            }
        }
        FansUserEntity userEntity = fansUserService.selectFansByOpenIdAndAppid("0", openid, appid);
        if (null == userEntity) {
            FansUserEntity dto = new FansUserEntity();
            dto.setFansId(fansId);
            dto.setType(0);
            dto.setAppId(appid);
            dto.setOpenId(openid);
            dto.setCreatedAt(new Date());
            fansUserService.save(dto);
            log.info("请求地址：/api/fans/getCodePlaceOpenid，返回结果：{}", JSONObject.toJSONString(dto));
            return dto;
        } else {
            log.info("请求地址：/api/fans/getCodePlaceOpenid，返回结果：{}", JSONObject.toJSONString(userEntity));
            return userEntity;
        }
    }

    /**
     * 小程序用户注销功能
     *
     * @return
     */
    public boolean delFanUser(Integer state, String phone, String code, Long userId) {
        if (null == state) {
            throw new BizException("请求参数缺失！");
        }
        if (state.intValue() == 1) {
            JSONObject smsCode = SmsUtil.getSmsCOde(CS.SYS_ROLE_TYPE.MCH, phone, 9);
            if (null == smsCode) {
                throw new BizException("验证码已过期！");
            }
            String smsCodeRedis = smsCode.getString("code");
            if (!smsCodeRedis.equals(code)) {
                throw new BizException("验证码错误");
            }
        }
        log.info("c端小程序用户注销功能，请求地址：/api/fans/delFanUser，请求参数： state：{}", state);
        boolean flag = this.fansUserService.lambdaUpdate()
                .set(FansUserEntity::getState, state)
                .set(FansUserEntity::getLogoutTime, new Date())
                .eq(FansUserEntity::getFansUserId, userId)
                .update();
        return flag;
    }

    public boolean userExit(Long fansId, Long userId) {
        LambdaQueryWrapper<FansUserEntity> fansUserEntityLambdaQueryWrapper = FansUserEntity.gw();
        fansUserEntityLambdaQueryWrapper.eq(FansUserEntity::getFansId, fansId);
        fansUserEntityLambdaQueryWrapper.eq(FansUserEntity::getFansUserId,userId);
        FansUserEntity entity = fansUserService.getOne(fansUserEntityLambdaQueryWrapper);
        // 0未登录 1已登录（退出登录置为0）
        entity.setIsLogin(0);
        boolean flag = fansUserService.updateById(entity);
        return flag;
    }

    public boolean updates(FansEntity object, Long fansId) {
        object.setPhone(null);//不更新手机号
        FansEntity result = new FansEntity();
        BeanUtils.copyProperties(object, result);

        result.setFansId(fansId);
        if (Objects.isNull(result.getFansId())) {
            throw new BizException("网络故障，请稍后重试！");
        }
        boolean flag = this.updateById(result);
        return flag;
    }

    // 新增支付公众号用户
    public FansEntity insertFansEntity(String openid, String locationAgentNo) {
        FansEntity entity = fansMapper.selectFansByOpenId(openid, locationAgentNo);
        if (Objects.isNull(entity)) {
            // 新建用户
            FansEntity fansEntity = new FansEntity();
            fansEntity.setCreatedAt(new Date());
            fansEntity.setPayOpenId(openid);
            int insert = fansMapper.insert(fansEntity);
            log.info("用户注册支付公众号信息：{}", JSON.toJSONString(fansEntity));
            if (insert > 0) {
                return fansEntity;
            } else {
                throw new BizException("用户异常！");
            }
        }
        log.info("用户注册支付公众号信息：{}", JSON.toJSONString(entity));
        return entity;
    }

    /**
     * 0自然流量
     * <p>
     * 1转发朋友/群 ，对应字段有：
     * activity_id, inviter_id (用户userId)
     * <p>
     * 2公众号渠道码 ，对应字段有：
     * activity_channel_id, inviter_id (公众号appId)
     * <p>
     * 3广告，对应字段有：
     * activity_id, inviter_id (微信WeChat，抖音TikTok)
     * <p>
     * 4扫码领券 ，对应字段有：
     * activityId, inviter_id (用户userId)
     * <p>
     * 5分享到朋友圈 ，对应字段有：
     * activity_id, inviter_id (用户userId)
     *
     * @param inviterType
     * @param inviterInfo
     */
    public void insertFansSource(Integer inviterType, String inviterInfo, Long fansId, String appid) {
        log.info("用户来源：类型：{}，参数：{}，用户fansId：{}", inviterType, inviterInfo, fansId);
        if (StringUtils.isEmpty(inviterInfo)) {
            log.info("用户来源信息为空");
            return;
        }
        inviterType = null == inviterType ? 0 : inviterType;
        FansSourceEntity entity = new FansSourceEntity();
        entity.setFansId(fansId);
        entity.setInviterType(inviterType);
        entity.setCreatedAt(new Date());
        JSONObject inviterInfoJson = JSONObject.parseObject(inviterInfo);
        if (inviterInfo.contains("activityId")) {
            entity.setActivityId(inviterInfoJson.getLong("activityId"));
        }
        if (1 == inviterType) {
            JSONObject object = JSONObject.parseObject(inviterInfo);
            entity.setInviterId(object.getLong("inviterId"));
        } else if (2 == inviterType) {
//            entity.setActivityChannelId(inviterInfoJson.getLong("channelId"));
            JSONObject object = JSONObject.parseObject(inviterInfo);
            entity.setInviterId(object.getLong("channelId"));
            String channelCode = inviterInfoJson.getString("channelCode");
            Integer channelType = inviterInfoJson.getInteger("channelType");
            if (0 == channelType) {
                //机构人员渠道码活动
                LambdaQueryWrapper<AgentEmployeeEntity> gw = AgentEmployeeEntity.gw();
                gw.eq(AgentEmployeeEntity::getEmployeeNo, channelCode);
                AgentEmployeeEntity agentEmployeeEntity = agentEmployeeService.getOne(gw);
                entity.setAgentNo(agentEmployeeEntity.getAgentNo());
            } else if (1 == channelType) {
                //商户渠道码活动
                MchInfoEntity mchInfo = mchInfoService.getById(channelCode);
                entity.setAgentNo(mchInfo.getAgentNo());
            } else if (2 == channelType) {
                //机构网点渠道码活动
                AgentInfoEntity agentInfo = agentInfoService.getById(channelCode);
                entity.setAgentNo(agentInfo.getAgentNo());
            }
        } else if (3 == inviterType) {
            JSONObject object = JSONObject.parseObject(inviterInfo);

        } else if (4 == inviterType) {
            JSONObject object = JSONObject.parseObject(inviterInfo);
            entity.setInviterId(object.getLong("qrcodeRecordId"));
        } else if (5 == inviterType) {
            JSONObject object = JSONObject.parseObject(inviterInfo);

        }else if (6 == inviterType) {
            JSONObject object = JSONObject.parseObject(inviterInfo);
            entity.setInviterId(object.getLong("inviterId"));
        }
        entity.setAppId(appid);
        log.info("用户来源信息：{}", JSONObject.toJSONString(entity));
        fansSourceService.getBaseMapper().insert(entity);
    }

    /**
     * 会员管理-列表查询
     *
     * @param page
     * @return
     */
    public IPage<FansEntity> getList1(IPage<FansEntity> page) {
        // 会员ID集合
        List<Long> fansIds = page.getRecords().stream().map(FansEntity::getFansId).collect(Collectors.toList());

        // 根据会员ID获取用户ID
        List<FansUserEntity> list = fansUserService.list(FansUserEntity.gw().eq(FansUserEntity::getType, 1).in(FansUserEntity::getFansId, fansIds));
        Map<Long, Long> map = list.stream().collect(Collectors.toMap(FansUserEntity::getFansId, FansUserEntity::getFansId, (a, b) -> a));

        // 数据脱敏
        page.getRecords().forEach(i -> {
            i.setPhone(DesensitizedUtil.mobilePhone(i.getPhone()));
        });
        return page;
    }

    public IPage<FansVO> getList(IPage page, FansDTO dto) {
        if (ObjectUtils.isNotEmpty(dto.getAgentNo())) {
            dto.setAgentNos(agentInfoService.queryAllSubAgentNo(dto.getAgentNo()));
            dto.setAgentNo(null);
        }
        IPage<FansVO> getList = fansMapper.getList(page, dto);
        // 如果是空，直接返回
        if (getList.getRecords().isEmpty()) {
            return getList;
        }

        for (FansVO i : getList.getRecords()) {
            if (i.getCstmNo() == null || i.getCstmName() == null) {
                i.setIsAustState(1L);
            } else {
                i.setIsAustState(0L);
            }

            if (i.getFfqyState() == null) {
                i.setFfqyState(2);
            }
            i.setPhone(DesensitizedUtil.mobilePhone(i.getPhone()));
            i.setCstmName(DesensitizedUtil.chineseName(i.getCstmName())); // 脱敏真实姓名
        }
        return getList;
    }

    public List<FansVO> getList(FansDTO dto) {
        if (ObjectUtils.isNotEmpty(dto.getAgentNo())) {
            dto.setAgentNos(agentInfoService.queryAllSubAgentNo(dto.getAgentNo()));
            dto.setAgentNo(null);
        }
        List<FansVO> getList = fansMapper.getList(dto);
        // 如果是空，直接返回
        if (getList.isEmpty()) {
            return getList;
        }

        for (FansVO i : getList) {
            if (i.getCstmNo() == null || i.getCstmName() == null) {
                i.setIsAustState(1L);
            } else {
                i.setIsAustState(0L);
            }

            if (i.getFfqyState() == null) {
                i.setFfqyState(2);
            }
            i.setPhone(DesensitizedUtil.mobilePhone(i.getPhone()));
            i.setCstmName(DesensitizedUtil.chineseName(i.getCstmName())); // 脱敏真实姓名
        }
        return getList;
    }

    public FansDTO getFansDetail(Long fansId, String agentNo) {
        return fansMapper.getFansDetail(fansId, agentNo);
    }


    /**
     * 会员领奖记录
     *
     * @param iPage
     * @param fansAwardDTO
     * @return
     */
    public IPage<FansAwardDTO> getFansAndFansAward(IPage iPage, FansAwardDTO fansAwardDTO) {
        if (ObjectUtils.isNotEmpty(fansAwardDTO.getAgentNo())) {
            fansAwardDTO.setAgentNos(agentInfoService.queryAllSubAgentNo(fansAwardDTO.getAgentNo()));
            fansAwardDTO.setAgentNo(null);
        }
        IPage<FansAwardDTO> fansAwardList = fansMapper.getFansAndFansAward(iPage, fansAwardDTO);
        // 根据奖品类型查询对应奖品名称
        Map<Integer, List<Long>> awardTypeMappingAwardIdListMap = fansAwardList.getRecords().stream()
                .collect(Collectors.groupingBy(FansAwardDTO::getAwardType,
                        Collectors.mapping(FansAwardDTO::getAwardId, Collectors.toList())));

        Map<Long, String> totalAwardNameMap = new HashMap<>();
        Integer awardType = Optional.ofNullable(fansAwardDTO.getAwardType()).orElse(-1);

        try {
            switch (awardType) {
                case 0:
                    addAwardNames(0, awardTypeMappingAwardIdListMap.get(0), totalAwardNameMap);
                    break;
                case 1:
                    addAwardNames(1, awardTypeMappingAwardIdListMap.get(1), totalAwardNameMap);
                    break;
                case 2:
                    addAwardNames(2, awardTypeMappingAwardIdListMap.get(2), totalAwardNameMap);
                    break;
                default:
                    for (Map.Entry<Integer, List<Long>> entry : awardTypeMappingAwardIdListMap.entrySet()) {
                        addAwardNames(entry.getKey(), entry.getValue(), totalAwardNameMap);
                    }
                    break;
            }
        } catch (Exception e) {
            log.error("赋值奖品名称错误：{}", e.getMessage());
        }

        // 一次性遍历设置AwardName
        fansAwardList.getRecords().forEach(record ->
                record.setAwardName(totalAwardNameMap.get(record.getAwardId()))
        );

        return fansAwardList;
    }

    /**
     * 赋值奖品名称
     *
     * @param type     奖品类型
     * @param awardIds 奖品ID集合
     * @param totalMap 奖品名称集合
     */
    private void addAwardNames(int type, List<Long> awardIds, Map<Long, String> totalMap) {
        if (awardIds == null || awardIds.isEmpty()) return;

        try {
            Map<Long, String> typeMap = getAwardNameMap(type, awardIds);
            totalMap.putAll(typeMap);
        } catch (Exception e) {
            log.error("获取奖品名称错误：{}", e.getMessage());
        }
    }

    private Map<Long, String> getAwardNameMap(int type, List<Long> awardIds) {
        return switch (type) {
            case 0 -> getNamesFromCoupon(awardIds);
            case 1 -> getNamesFromGoods(awardIds);
            case 2 -> getNamesFromVirtual(awardIds);
            default -> throw new IllegalArgumentException("Invalid award type: " + type);
        };
    }

    private Map<Long, String> getNamesFromCoupon(List<Long> couponIds) {
        List<AwardCouponEntity> list = awardCouponService.list(AwardCouponEntity.gw()
                .select(AwardCouponEntity::getCouponId, AwardCouponEntity::getCouponName)
                .in(AwardCouponEntity::getCouponId, couponIds));
        return list.stream().collect(Collectors.toMap(
                AwardCouponEntity::getCouponId,
                AwardCouponEntity::getCouponName));
    }

    private Map<Long, String> getNamesFromGoods(List<Long> goodsIds) {
        List<AwardGoodsEntity> list = awardGoodsService.list(AwardGoodsEntity.gw()
                .select(AwardGoodsEntity::getGoodsId, AwardGoodsEntity::getGoodsName)
                .in(AwardGoodsEntity::getGoodsId, goodsIds));
        return list.stream().collect(Collectors.toMap(
                AwardGoodsEntity::getGoodsId,
                AwardGoodsEntity::getGoodsName));
    }

    private Map<Long, String> getNamesFromVirtual(List<Long> virtualIds) {
        List<AwardVirtualVO> list = awardVirtualService.getListByVirtualIdList(virtualIds);
        return list.stream().collect(Collectors.toMap(
                AwardVirtualVO::getVirtualId,
                AwardVirtualVO::getGoodsName));
    }

    /**
     * 会员管理-获奖记录
     *
     * @param page
     * @return
     */
    public IPage<FansAwardDTO> fansAndFansAward(IPage<FansAwardDTO> page) {
        // 会员ID集合
        List<Long> fansIds = page.getRecords().stream().map(FansAwardDTO::getFansId).collect(Collectors.toList());

        // 根据会员ID获取用户ID
        List<FansUserEntity> list = fansUserService.list(FansUserEntity.gw().eq(FansUserEntity::getType, 1).in(CollUtil.isNotEmpty(fansIds), FansUserEntity::getFansId, fansIds));
//        Map<Long, Long> map = list.stream().collect(Collectors.toMap(FansUserEntity::getFansId, FansUserEntity::getFansUserId, (a, b) -> a));
        // 数据脱敏
        page.getRecords().forEach(i -> {
//            i.setUserId(map.get(i.getFansId()));
            i.setPhone(DesensitizedUtil.mobilePhone(i.getPhone()));
            i.setNickName(DesensitizedUtil.chineseName(i.getNickName()));
        });
        return page;
    }


    /**
     * 获取用户参与活动列表
     *
     * @return
     */
    public IPage<FansActivityVO> getFansActivity(IPage iPage, FansActivityDTO fansActivityDTO) {
        if (ObjectUtils.isNotEmpty(fansActivityDTO.getAgentNo())) {
            fansActivityDTO.setAgentNos(agentInfoService.queryAllSubAgentNo(fansActivityDTO.getAgentNo()));
            fansActivityDTO.setAgentNo(null);
        }
        return fansMapper.getFansActivity(iPage, fansActivityDTO, fansActivityDTO.getAgentNos());
    }


    public JSONObject getScoreOrcouponCount(Long fansId, String appId) {
        ScoreTotalEntity scoreTotalEntity = scoreTotalService.selectByFansId(fansId, appId);

        // 使用单个查询获取所有需要的数据
        List<FansAwardEntity> summaries = fansAwardService.getBaseMapper().selectList(new LambdaQueryWrapper<FansAwardEntity>()
                .eq(FansAwardEntity::getFansId, fansId)
                .eq(FansAwardEntity::getAppId, appId)
                .in(FansAwardEntity::getAwardType, Arrays.asList(0, 1, 2)) // 卡券、实物、虚拟奖品
        );

        int coupon = 0; // 未使用的卡券
        int couponWaitOn = 0; // 待激活的卡券
        int goods = 0; // 实物
        int cdkNum = 0; // CDK 数量
        int rechargeNum = 0; // 充值数量

        for (FansAwardEntity summary : summaries) {
            switch (summary.getAwardType()) {
                case 0: // 卡券
                    if (summary.getState() == 0) {
                        coupon++;
                    } else if (summary.getState() == 3) {
                        couponWaitOn++;
                    }
                    break;
                case 1: // 实物
                    if (summary.getState() == Constants.FANS_AWARD_STATE.ACTIVATE) {
                        goods++;
                    }
                    break;
                case 2: // 虚拟奖品
                    if (summary.getState() == 0) { // 假设0为待使用状态
                        Integer type = virtualGoodsInsideService.getById(
                                virtualAwardService.getById(summary.getAwardId()).getVirtualInsideId()
                        ).getType();
                        if (type == 0) {
                            cdkNum++;
                        } else if (type == 1) {
                            rechargeNum++;
                        }
                    }
                    break;
            }
        }

        JSONObject jsonObject = new JSONObject();
        if (scoreTotalEntity != null) {
            jsonObject.put("score", scoreTotalEntity.getCurrentScore());
        } else {
            jsonObject.put("score", 0);
        }
        jsonObject.put("coupon", coupon);
        jsonObject.put("couponWaitOn", couponWaitOn);
        jsonObject.put("goods", goods);
        jsonObject.put("cdkNum", cdkNum);
        jsonObject.put("rechargeNum", rechargeNum);
        return jsonObject;
    }

    /**
     * 会员管理-参与活动列表查询
     *
     * @param page
     */
    public IPage<FansActivityVO> activityList(IPage<FansActivityVO> page) {

        // 数据脱敏
        page.getRecords().forEach(i -> {
            i.setPhone(DesensitizedUtil.mobilePhone(i.getPhone()));
            i.setNickName(DesensitizedUtil.chineseName(i.getNickName()));
        });
        return page;
    }


    /**
     * 民宿同步会员信息
     *
     * @param fansEntity
     * @return
     */
    public JSONObject syncFansMchInfo(FansEntity fansEntity, String agentNo) {
        JSONObject json = new JSONObject();
        // 查询用户实名信息
        FansAuthEntity fansAuthEntity = fansAuthService.getOne(FansAuthEntity.gw().eq(FansAuthEntity::getFansId, fansEntity.getFansId()).eq(FansAuthEntity::getAgentNo, agentNo));
        json.put("isAuth", ObjectUtils.isNotEmpty(fansAuthEntity) && ObjectUtils.isNotEmpty(fansAuthEntity.getCstmNo()) ? "true" : "false");

        if (ObjectUtils.isNotEmpty(fansAuthEntity) && ObjectUtils.isNotEmpty(fansAuthEntity.getCstmNo())) {
            // 查询资产等级接口
            Map<String, Integer> map = assetMonthService.getUserAssetLevel(fansAuthEntity.getCstmNo(), fansEntity.getFansId(), agentNo);
            if (map.get("userAssetLevel") != null) {
                LocalDate firstDayOfLastMonth = LocalDate.of(map.get("year"), map.get("lastMonth"), 1);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM");

                json.put("assetLevelDate", firstDayOfLastMonth.format(formatter));
                json.put("assetLevel", String.valueOf(map.get("userAssetLevel")));
                json.put("inSearch", map.get("inSearch"));
              /*  AgentEquityVO assetLevelEquity = agentEquityService.getAssetLevelEquity(map.get("userAssetLevel"), agentNo);
                if (assetLevelEquity != null) {
                    json.put("levelScore", String.valueOf(assetLevelEquity.getLevelScore()));
                }*/
            } else {
                LocalDate firstDayOfLastMonth = LocalDate.of(map.get("year"), map.get("lastMonth"), 1);
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM");
                json.put("assetLevelDate", firstDayOfLastMonth.format(formatter));
                json.put("inSearch", map.get("inSearch"));
            }
        }

        return json;
    }


    /**
     * 获取会员卡券数量
     * 待激活，待使用
     *
     * @param fansEntity
     * @return
     */
    public String syncFansCouponNum(FansEntity fansEntity) {
        Map<String, String> map = fansAwardService.getBaseMapper().syncFansCouponNum(fansEntity.getFansId());
        return JSONObject.toJSONString(map);
    }


    /**
     * 民宿同步会员卡券信息
     *
     * @param fansId
     * @param json
     * @return
     */
    public IPage<FansCouponsVo> syncFansCouponList(IPage page, Long fansId, JSONObject json) {
        Integer num = json.getInteger("num");
        Integer size = json.getInteger("size");
        if (null == size) {
            size = 10;
        }
        if (null == num) {
            num = 0;
        } else {
            num = (num - 1) * size;
        }
        page.setPages(num);
        page.setSize(size);
        return fansAwardService.getBaseMapper().syncFansCouponList(page, fansId, json);
    }

    /**
     * 校验手机用户验证码
     *
     * @param phone
     * @param smsCode
     * @param fansId
     */
    public void checkPhoneCode(String phone, String smsCode, Long fansId) {
        if (Objects.isNull(fansId) || StringUtils.isEmpty(phone) || StringUtils.isEmpty(smsCode)) {
            throw new BizException("请求参数缺失！");
        }
        String string = RedisUtil.getString(CS.getCacheKeySmsCode(CS.SYS_ROLE_TYPE.MCH, phone));
        boolean b = false;
        if (StringUtils.isEmpty(string)) {
            throw new BizException("手机号错误！");
        } else {
            JSONObject object = JSONObject.parseObject(string);
            String code = object.getString("code");
            String mobile = object.getString("mobile");
            if (code.equals(smsCode) && mobile.equals(phone)) {
                FansEntity fansEntity = new FansEntity();
                fansEntity.setFansId(fansId);
                fansEntity.setPhone(phone);
                b = updateById(fansEntity);
            } else {
                throw new BizException("手机号或验证码错误！");
            }
        }
        if (!b) {
            throw new BizException("认证失败！");
        }
    }

    /**
     * 获取用户认证商户
     *
     * @param fansDTO
     * @return
     */
    public IPage<FansVO> fansAuthAndMchList(IPage iPage, FansDTO fansDTO) {
        if (StrUtil.isBlank(fansDTO.getFlag())) {
            throw new BizException("请求参数缺失！");
        }
        if (ObjectUtils.isNotEmpty(fansDTO.getAgentNo())) {
            fansDTO.setAgentNos(agentInfoService.queryAllSubAgentNo(fansDTO.getAgentNo()));
            fansDTO.setAgentNo(null);
        }
        return fansMapper.getFansAuthAndMchList(iPage, fansDTO);
    }


    /**
     * 积分明细
     *
     * @param
     * @return
     */
    public IPage<ScoreRecordTotalVO> getRecordOfBlessings(IPage iPage, FansDTO fansDTO) {
        List<ScoreRecordTotalVO> recordOfBlessingplus = scoreRecordTotalMapper.getRecordOfBlessingplus(fansDTO);
        int a = 0;
        int b = 0;
        if (!recordOfBlessingplus.isEmpty()) {

            for (ScoreRecordTotalVO scoreRecordTotalVO : recordOfBlessingplus) {
                if (scoreRecordTotalVO.getFlag() == 1 || scoreRecordTotalVO.getFlag() == 2) {
                    a = a + scoreRecordTotalVO.getScore();
                } else {
                    b = b + scoreRecordTotalVO.getScore();
                }
            }
            b = b - a;
        }

        IPage<ScoreRecordTotalVO> recordOfBlessings = scoreRecordTotalMapper.getRecordOfBlessings(iPage, fansDTO);

        if (recordOfBlessings.getRecords().isEmpty()) {
            return recordOfBlessings;
        }
        for (ScoreRecordTotalVO scoreRecordTotalVO : recordOfBlessings.getRecords()) {
            scoreRecordTotalVO.setAlreadyScore(a);
            scoreRecordTotalVO.setNewScore(b);
        }

        if (recordOfBlessings.getRecords() == null || recordOfBlessings.getRecords().size() == 0) {
            List<ScoreRecordTotalVO> filteredList = new ArrayList<>();
            ScoreRecordTotalVO scoreRecordTotalVO = new ScoreRecordTotalVO();
            scoreRecordTotalVO.setAlreadyScore(a);
            scoreRecordTotalVO.setNewScore(b);
            filteredList.add(scoreRecordTotalVO);
            recordOfBlessings.setRecords(filteredList);
        }

        return recordOfBlessings;
    }

    /**
     * 积分明细
     *
     * @param
     * @return
     */
    public List<ScoreRecordTotalVO> getRecordOfBlessings(FansDTO fansDTO) {
        List<ScoreRecordTotalVO> recordOfBlessings = scoreRecordTotalMapper.getRecordOfBlessingplus(fansDTO);
        int a = 0;
        int b = 0;
        if (recordOfBlessings.isEmpty()) {
            return recordOfBlessings;
        }
        for (ScoreRecordTotalVO scoreRecordTotalVO : recordOfBlessings) {
            if (scoreRecordTotalVO.getFlag() == 1 || scoreRecordTotalVO.getFlag() == 2) {
                a = a + scoreRecordTotalVO.getScore();
            } else {
                b = b + scoreRecordTotalVO.getScore();
            }
        }
        b = b - a;
        for (ScoreRecordTotalVO scoreRecordTotalVO : recordOfBlessings) {
            scoreRecordTotalVO.setAlreadyScore(a);
            scoreRecordTotalVO.setNewScore(b);
        }

        if (fansDTO.getFlag() != null && !fansDTO.getFlag().equals("")) {
            if (fansDTO.getFlag().equals("0")) {
                List<ScoreRecordTotalVO> filteredList = recordOfBlessings.stream()
                        .filter(vo -> vo.getFlag() == 0)
                        .collect(Collectors.toList());
                recordOfBlessings = filteredList;
            } else if (fansDTO.getFlag().equals("1")) {
                List<ScoreRecordTotalVO> filteredList = recordOfBlessings.stream()
                        .filter(vo -> vo.getFlag() == 1)
                        .collect(Collectors.toList());
                recordOfBlessings = filteredList;
            } else if (fansDTO.getFlag().equals("2")) {
                List<ScoreRecordTotalVO> filteredList = new ArrayList<>();
                for (ScoreRecordTotalVO scoreRecordTotalVO : recordOfBlessings) {
                    if (scoreRecordTotalVO.getFlag() == 2) {
                        filteredList.add(scoreRecordTotalVO);
                    }
                }
                recordOfBlessings = filteredList;
            }
        }

        return recordOfBlessings;
    }

    /**
     * 查询用户-重置商户号
     *
     * @param
     * @return
     */
    public IPage<FansVO> getFansMchInfo(IPage iPage, FansDTO dto) {
        return fansMapper.getFansMchInfo(iPage, dto);
    }

    public String ListExportWechat(List<FansVO> list, HttpServletResponse response) {

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment; filename=exportedData.xlsx");


        String successFileName = String.format("./temp/userList/%s.xlsx", DateUtil.date().getTime());

        File successFile = new File(successFileName);
        BigExcelWriter writer = ExcelUtil.getBigWriter(successFile);
        writer.renameSheet("用户导出");
        writer.addHeaderAlias("openId", "客户标识");
        writer.addHeaderAlias("fansUserId", "客户ID");
        writer.addHeaderAlias("agentNo", "归属机构");
        writer.addHeaderAlias("nickName", "昵称");
        writer.addHeaderAlias("authPhone", "实名手机号");
        writer.addHeaderAlias("cstmName", "真实姓名");
        writer.addHeaderAlias("isAustState", "是否实名（0是1否）");
        writer.addHeaderAlias("cstmNo", "实名唯一ID");
        writer.addHeaderAlias("firstIsAustTime", "实名认证时间");
        writer.addHeaderAlias("firstEntryTime", "首次登录时间");
        writer.addHeaderAlias("headPic", "头像");
        // 设置只使用别名，确保数据正确写入指定列
        writer.setOnlyAlias(true);
        // 写入数据列表到Excel
        writer.write(list);
        //自动调整 Excel 文件中所有列的宽度
        writer.autoSizeColumnAll();
        // 关闭writer，释放资源
        writer.close();
        try {
            MultipartFile multipartFile = new MockMultipartFile(successFileName, successFile.length(), new FileInputStream(successFile));
            String successUrl = ossFileService.singleFileUpload(multipartFile, OssFileConfig.BIZ_TYPE.UPLOAD);
            // 添加oos上传记录
            OssRecordEntity ossRecordEntity = new OssRecordEntity();
            ossRecordEntity.setBizType("userList");
            ossRecordEntity.setOssUrl(successUrl);
            ossRecordEntity.setFileSize(successFile.length());
            ossRecordEntity.setUploadType(Constants.OSS_UPLOAD_TYPE.USER_LIST_INFORMATION);
            ossRecordEntity.setCreatedAt(new Date());
            ossRecordService.save(ossRecordEntity);
            return successUrl;
        } catch (Exception e) {
            throw new BizException(e.getMessage());
        }

    }

    public String RecordExportWechat(List<ScoreRecordTotalVO> list, HttpServletResponse response) {

        for (ScoreRecordTotalVO scoreRecordTotalVO : list) {
            if (scoreRecordTotalVO.getFlag() == 0) {
                scoreRecordTotalVO.setFlagName("获得福分");
            }
            if (scoreRecordTotalVO.getFlag() == 1) {
                scoreRecordTotalVO.setFlagName("消耗福分");
                scoreRecordTotalVO.setScore(-scoreRecordTotalVO.getScore());
            }
            if (scoreRecordTotalVO.getFlag() == 2) {
                scoreRecordTotalVO.setFlagName("福分过期");
                scoreRecordTotalVO.setScore(-scoreRecordTotalVO.getScore());
            }
        }

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment; filename=exportedData.xlsx");

        String successFileName = String.format("./temp/scorexq/%s.xlsx", DateUtil.date().getTime());

        File successFile = new File(successFileName);
        BigExcelWriter writer = ExcelUtil.getBigWriter(successFile);

        writer.renameSheet("福分详情导出");
        writer.addHeaderAlias("flagName", "变动类型");
        writer.addHeaderAlias("score", "变动福分");
        writer.addHeaderAlias("name", "变动原因");
        writer.addHeaderAlias("createdAt", "变动时间");
        writer.setOnlyAlias(true);
        writer.write(list);
        writer.autoSizeColumnAll();
        // 关闭writer，释放资源
        writer.close();

        try {
            MultipartFile multipartFile = new MockMultipartFile(successFileName, successFile.length(), new FileInputStream(successFile));
            String successUrl = ossFileService.singleFileUpload(multipartFile, OssFileConfig.BIZ_TYPE.UPLOAD);
            // 添加oos上传记录
            OssRecordEntity ossRecordEntity = new OssRecordEntity();
            ossRecordEntity.setBizType("scorexq");
            ossRecordEntity.setOssUrl(successUrl);
            ossRecordEntity.setFileSize(successFile.length());
            ossRecordEntity.setUploadType(Constants.OSS_UPLOAD_TYPE.USER_LIST_INFORMATION);
            ossRecordEntity.setCreatedAt(new Date());
            ossRecordService.save(ossRecordEntity);
            return successUrl;
        } catch (Exception e) {
            throw new BizException(e.getMessage());
        }
    }

    /**
     * 接受邀请转介
     */
    public ApiRes inviterConfirmAward(String time, Long inviterId, Long userId, String appId, String agentNo) {
        List<String> officialAccountsAppIdList = agentScoreRuleMapper.officialAccountsAppIdList(agentNo);
        String officialAppId = null;
        if (ObjectUtils.isNotEmpty(officialAccountsAppIdList)){
            officialAppId = officialAccountsAppIdList.get(0);
        }
        List<AgentAppVO> agentAppVOList = agentAppMapper.selectByAgentNoAndTypeAndAppid(null, 0, officialAppId);
        if (ObjectUtils.isEmpty(agentAppVOList)){
            return ApiRes.customFail("网络故障:请稍后再试");
        }
        AgentAppVO lite = agentAppVOList.get(0);
        // 禁止拉新本人
        if (inviterId.equals(userId)) {
            return ApiRes.customFail("拉新失败:请勿拉新本人");
        }
        LambdaQueryWrapper<InviterRecordEntity> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(InviterRecordEntity::getFansId,userId);
        InviterRecordEntity one = inviterRecordService.getOne(queryWrapper);
        if (null != one) {
            return ApiRes.customFail("您已确认邀请，请勿重复确认");
        }
        int i = inviterRecordService.inviterConfirmAward(inviterId, userId, officialAppId, time, appId);
        if (1 == i) {
            return ApiRes.customFail("拉新失败:您非新客");
        } else if (2 == i) {
            return ApiRes.fail(ApiCodeEnum.LITE_USER_NO_OFFICIAL_ERROR,lite.getImgUrl());
        }else if( 3 == i ){
            return ApiRes.customFail("拉新失败:缺失关注公众号信息");
        }else if( 4 == i){
            return ApiRes.customFail("拉新失败:缺失邀请人信息");
        }else if( 5 == i){
            return ApiRes.customFail("网络故障:请稍后再试");
        }else if( 6 == i){
            return ApiRes.customFail("请先登录:再进行关注公众号【"+lite.getName()+"】");
        }
        return ApiRes.ok("邀约成功");
    }

    public IPage<AllFansInfoDTO> getAllFansInfoDTO(IPage iPage, AllFansInfoDTO dto) {
        return fansMapper.getAllFansInfoDTO(iPage,dto);
    }

    /**
     * 分页获取用户资产等级数据
     */

    public List<FansVO> getAssetLevelsByPage(int page, int pageSize, String agentNo) {
        int offset = (page - 1) * pageSize;
        // 调用Mapper接口的分页查询方法
        List<FansVO> fansList = fansMapper.assetLevel(pageSize,offset,agentNo);
        return fansList;
    }
}
